package main

import (
	"fmt"
	"io"
	"os"
	"reflect"
)

type Reader interface {
	ReadBook()
}

type Writer interface {
	WriteBook()
}

type Book struct{}

func (this *Book) ReadBook() {
	fmt.Println("Read a Book")
}

func (this *Book) WriteBook() {
	fmt.Println("Write a Book")
}

func (this User) SetUsername(username string) {
	this.Name = username
}

func ReflectNum(arg interface{}) {
	fmt.Println(reflect.TypeOf(arg))
	fmt.Println(reflect.ValueOf(arg))
}

func reflectUser(arg interface{}) {
	inputType := reflect.TypeOf(arg)
	inputValue := reflect.ValueOf(arg)
	fmt.Println(inputType)
	fmt.Println(inputValue)
	for i := 0; i < inputType.NumField(); i++ {
		field := inputType.Field(i)
		value := inputValue.Field(i)
		fmt.Printf("%s %v = %v\n", field.Name, field.Type, value)
	}

	for i := 0; i < inputType.NumMethod(); i++ {
		method := inputType.Method(i)
		fmt.Printf("%s %v\n", method.Name, method.Type)
	}
}

func main() {
	var a string
	a = "str111"

	var allType interface{}
	allType = a

	str, _ := allType.(string)
	fmt.Println(str)

	file, err := os.OpenFile("D:\\zhj_go\\src\\golang_study\\reflect_\\111.txt", os.O_RDWR, 0)
	if err != nil {
		fmt.Println("open file error:", err)
		return
	}
	var r io.Reader
	r = file

	var w io.Writer
	w = r.(io.Writer)

	w.Write([]byte("hello world111\nfengege"))

	fmt.Println("==================")

	bb := &Book{}

	var rr Reader
	rr = bb
	rr.ReadBook()

	var ww Writer
	ww = rr.(Writer)
	ww.WriteBook()

	fmt.Println("==================")

	var num float32 = 123.123
	ReflectNum(num)

	fmt.Println("==================")
	reflectUser(User{"zhj", 12, 4})
	fmt.Println("==================")

	var re resume
	findTag(&re)
}

type resume struct {
	Name string `json:"name" info:"name" doc:"我的名字"`
	Sex  string `info:"sex"`
}

func findTag(str interface{}) {
	fmt.Println(reflect.TypeOf(str))
	t := reflect.TypeOf(str).Elem()
	for i := 0; i < t.NumField(); i++ {
		taginfo := t.Field(i).Tag.Get("info")
		tagdoc := t.Field(i).Tag.Get("doc")
		fmt.Println("info", taginfo, " doc:", tagdoc)
	}
}

type User struct {
	Name  string
	Age   int
	Level int
}

func (this *User) SayHello() {
	fmt.Println("user hello")
	fmt.Printf("%v \n", this)
}
